﻿using System;
using System.Web;
using Cms.Domain.Authentication;
using Cms.Utilities;
using NHibernate;

namespace Cms.Data.ORM
{
    public class SessionManager : IHttpModule
    {
        private static readonly string _key = "NHibernateSession";

        private AuditLogInterceptor _interceptor;

        public static ISession Current
        {
            get
            {
                HttpContext currentContext = HttpContext.Current;
                var session = (ISession)currentContext.Items[_key];

                if (session == null)
                {
                    session = NHibernateSessionFactory.OpenSession();
                    currentContext.Items[_key] = session;
                }
                return session;
            }
        }

        #region IHttpModule Members

        public void Init(HttpApplication application)
        {
            application.BeginRequest += BeginRequest;
            application.AuthorizeRequest += AuthorizeRequest;
            application.EndRequest += EndRequest;
        }
        
        public void Dispose()
        {
        }

        #endregion

        private void BeginRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            HttpContext context = application.Context;
            try
            {
                _interceptor = new AuditLogInterceptor();
                ISession session = NHibernateSessionFactory.OpenSession(_interceptor);
                _interceptor.Session = session;
                context.Items[_key] = session;
            }
            catch (Exception ex)
            {
                Logging.LogError("SessionManager.context_BeginRequest", ex);
                throw;
            }
        }

        protected void AuthorizeRequest(object sender, EventArgs e)
        {
            var user = ((HttpApplication)sender).Context.User;
            if (user == null || user.Identity == null || !user.Identity.IsAuthenticated || string.IsNullOrEmpty(user.Identity.Name))
            {
                return;
            }
            try
            {
                AuthenticatedUser authenticatedUser = Conversion.ToAuthenticatedUser(user.Identity.Name);
                _interceptor.AdministratorID = authenticatedUser.AdministratorID;
                _interceptor.UserID = authenticatedUser.UserID;
            }
            catch (Exception ex)
            {
                Logging.LogError("AdministratorID or UserID could not be retrieved in SessionManager.AuthorizeRequest", ex);
            }
        }

        private void EndRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            HttpContext context = application.Context;
            var session = (ISession)context.Items[_key];

            if (session != null)
            {
                session.Close();
            }
            context.Items[_key] = null;
        }
    }
}